﻿using LitJson;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;

namespace SimpleFramework
{
#if UNITY_EDITOR
    public class ResManager : TMonoSingletonX<ResManager>, ITimer
#else
    public class ResManager : TSingleton<ResManager>, ITimer
#endif
    {
        private const string BundleExtensionName = "ab";
        private const string BundleName = "bundle/bundle";
        private const string ConfigName = "bundle/res.config";
        private Dictionary<string, ResAssetBundle> m_BundleDict = new Dictionary<string, ResAssetBundle>();
#if UNITY_EDITOR
        [SerializeField]
#endif 
        private List<ResAssetBundle> m_BundleList = new List<ResAssetBundle>();

        private Dictionary<string, string> m_Asset2BundleDict = new Dictionary<string, string>();

        private AssetBundleManifest m_AssetBundleManifest;

        private float m_LastTime = 0;


        public void Init(System.Action onFinish)
        {
            int loadCount = 2;
            var cfgUrl = PathSystem.Instance.Search(ConfigName);
            FileSystem.Instance.LoadFile(cfgUrl, (ILoader loader, byte[] bytes) =>
            {
                ParseConfig(bytes);
                loadCount--;
                if (loadCount <= 0)
                    onFinish?.Invoke();
            });

            var binUrl = PathSystem.Instance.Search(BundleName);
            FileSystem.Instance.LoadAssetBundle(binUrl, (loader, ab) => {
                m_AssetBundleManifest = ab.LoadAsset<AssetBundleManifest>("assetbundlemanifest");
                //ab.Unload(true);
                loadCount--;
                if (loadCount <= 0)
                    onFinish?.Invoke();
            });

            TimerSystem.Instance.Add(this);
        }

        private void ParseConfig(byte[] bytes)
        {
            using (var file = new MemoryStream(bytes))
            {
                using (var reader = new StreamReader(file))
                {
                    m_Asset2BundleDict.Clear();
                    string key = null;
                    while (reader.Peek() != -1)
                    {
                        var line = reader.ReadLine();
                        if (string.IsNullOrEmpty(line))
                            continue;

                        if (line.StartsWith("++++"))
                        {
                            m_Asset2BundleDict.Add(line.Substring(4), key + ".ab");
                        }
                        else
                        {
                            key = line;
                        }
                    }
                }
            }

            Debug.Log("加载资源配置完成");
        }

        public ResAssetBundle GetAssetBundle(string url)
        {
            return m_BundleDict[url];
        }

        /// <summary>
        /// 获取依赖列表
        /// </summary>
        /// <param name="bundlePath"></param>
        /// <returns></returns>
        public string[] GetAllDependencies(string bundlePath)
        {
            return m_AssetBundleManifest.GetAllDependencies(bundlePath);
        }

        /// <summary>
        /// 获取ResAssetBundle， 没有就创建一个
        /// </summary>
        /// <param name="bundlePath"></param>
        /// <returns></returns>
        public ResAssetBundle GetAssetBundleOrCreate(string bundlePath)
        {
            ResAssetBundle assetBundle;
            if (!m_BundleDict.TryGetValue(bundlePath, out assetBundle))
            {
                assetBundle = new ResAssetBundle(bundlePath);
                m_BundleDict.Add(bundlePath, assetBundle);
                m_BundleList.Add(assetBundle);
            }
            return assetBundle;
        }

        public ResAssetBundle LoadAssetBundle(
            string bundlePath, 
            UnityAction<ResAssetBundle> onComplete = null, 
            UnityAction<ResAssetBundle, string> onFailure = null, 
            UnityAction<ILoader, float> onProgress = null)
        {
            var asset = GetAssetBundleOrCreate(bundlePath);
            asset.ListenLoadComplete(onComplete);
            asset.ListenLoadFailure(onFailure);
            return asset;
        }

        public ResAssetBundle LoadAssetBundleByAsset(
            string assetPath,
            UnityAction<ResAssetBundle> onComplete = null,
            UnityAction<ResAssetBundle, string> onFailure = null,
            UnityAction<ILoader, float> onProgress = null)
        {
            string bundlePath;
            if (m_Asset2BundleDict.TryGetValue(assetPath, out bundlePath))
            {
                Debug.Log(bundlePath);
                return LoadAssetBundle(bundlePath, onComplete, onFailure, onProgress);
            }
            Debug.LogError($"找不到资源：{assetPath}");
            return null;
        }

        public bool Update()
        {
            if (Timer.time - m_LastTime < 10f)
                return false;

            m_LastTime = Timer.time;

            int i = 0;
            ResAssetBundle bundle;
            while (i < m_BundleList.Count)
            {
                bundle = m_BundleList[i];
                if (bundle.CheckRecycle())
                {
                    m_BundleDict.Remove(bundle.Url);
                    m_BundleList.RemoveAt(i);
                    bundle.Destroy();
                }
                else
                {
                    ++i;
                }
            }

            return false;
        }
    }
}